千万级并发系统
大纲
| 阶段 | 核心挑战 | 典型技术/设计 | 目标能力 |
|---|---|---|---|
| 1. 单机单体 | 功能验证、快速迭代 | 单体应用 + 单机 DB | MVP上线速度 |
| 2. 读写分离 | 数据库瓶颈 | 主从复制、读写路由 | QPS 10 万级 |
| 3. 缓存加速 | 熔断热点、降低延迟 | Redis、Memcached;本地缓存 | ms 级响应 |
| 4. 数据库扩展 | 数据量 & 流量猛增 | 分库分表、分区、Consistent Hash | TB-PB 级数据 |
| 5. 异步化 & 松耦合 | 高并发 & 高可用 | 消息队列(Kafka/RabbitMQ)、事件驱动 | 流量削峰、系统解耦 |
| 6. 微服务 & 云原生 | 团队协作、快速弹性 | 服务治理(Service Mesh)、容器 & K8s、CI/CD | 全球多活、弹性伸缩 |
1. 单机单体

1.1 垂直扩展与水平扩展
| 维度 | 垂直扩展 (Vertical Scaling) | 水平扩展 (Horizontal Scaling) |
|---|---|---|
| 做法 | 给同一台服务器加更多资源:CPU、RAM、SSD … | 增减多台服务器;对外表现为一个资源池 |
| 优点 | - 架构简单,代码几乎零改动 - 统一内存空间,避免分布式一致性难题 | - 理论上可无限扩容 - 天然具备冗余与故障转移 - 可按需弹性伸缩,资源利用 率更高 |
| 局限 | - 存在硬件上限,价格随规格呈指数增长 - 无冗余:机器宕机=业务停机 | - 开发 & 运维复杂:需负载均衡、状态拆分、分布式数据层 - 网络开销、跨节点一致性需额外设计 |
| 典型场景 | 单体应用、PoC、业务早期、内部管理系统 | 大规模 Web / 移动应用、分布式存储与计算、云原生微服务 |
| 成本模型 | CAPEX:一次性硬件投入高;升级需停机 | OPEX:按量付费、可渐进投入;云厂商 Auto-Scaling |
| 常见技术要点 | NUMA 优化、内核参数调优、超线程 | 负载均衡 (LVS/Nginx/ALB)、容器编排 (K8s)、分库分表、Cache、MQ |
1.2 负载均衡

| 维度 | 说明 |
|---|---|
| 工作方式 | 公开 1 个公网 IP,隐藏后端 Web 服务器私网 IP; 所有客户端先连 LB,再由 LB 把请求分发到健康实例 |
| 解决问题 | - 单点故障:任一 Web 实例宕机,流量自动切到其他实例,业务不停服 - 水平扩容:流量飙升时,只需向服务器池加节点,LB 即刻开始转发,无需停机 |
| 安全隔离 | Web 服务器仅暴露私有 IP,外网不可直连,减少攻击面 |
| 健康检查 | 周期性探测 TCP/HTTP;探测失败即将实例摘除,恢复后再加入 |
| 常见调度算法 | 轮询、最少连接、源地址 Hash、加权轮询等 |
| 部署形态 | 软件(Nginx/OpenResty、HAProxy)、硬件(F5/Array)、云托管(AWS ALB、阿里云 SLB) |
| 层级 | L4(TCP/UDP,性能高,逻辑简单)L7(HTTP/HTTPS,可做 Cookie 粘性、HTTPS 终端、WAF) |
2. 读写分离
- 读写分离

- 负载均衡+读写分离+多服务

2.1 核心要点
读写分离 = “让写保持强一致,让读获得无限扩展”。只要把复制延迟监控到位、切主流程自动化,它就是成本最低、见效最快的数据库高可用与读扩展方案。
| 维度 | 关键说明 |
|---|---|
| 目标 | 1. 写请求不被读请求拖慢 2. 读请求可横向扩容 3. 主库通过复制(binlog / WAL)把变更同步到从库,实现写-读解耦、横向扩展读能力。 |
| 基本架构 | 1 台 主库 (Master) 负责 写 ≥1 台 从库 (Slave) 负责 只读 |
| 主流程 | INSERT/UPDATE/DELETE→ Master → 生成 binlog → 复制线程把 binlog 重放到每个 Slave → Slave 只接受SELECT |
| 为什么需要 | 关键信息互联网业务普遍 读远多于写(10:1 ~ 100:1),单库难以支撑高并发读,且缺乏冗余。 |
| 复制延迟 | 主写后立即读可能拿到旧数据,需要 Hint 强制走主或读写一致性缓存 |
- 常见实现方式
| 层级 | 技术 & 说明 |
|---|---|
| 应用层 | Spring AOP + AbstractRoutingDataSource、MyBatis 注解最灵活;代码侵入小;适合单体或微服务单点扩容 |
| 中间件层 | ShardingSphere-JDBC/Proxy、MyCAT、ProxySQL、阿里云 DRDS YAML/SQL 诊断即可配置;后续可平滑接分片、影子库 |
| 数据库原生 | 云原生 RDS(Aurora、PolarDB、云 MySQL)的 只读副本 + Endpoint 无需改代码;由云厂商维护复制与健康检查 |
- 两阶段提交(2PC)
| 场景类型 | 典型业务 | 为什么必须 2PC? | 备注与替代方案 |
|---|---|---|---|
| 跨库原子写 | 订单表在 库 A,库存表在 库 B;一次下单要同时插入订单、扣减库存 | 必须保证 要么全部成功,要么全部回滚,否则出现“有订单却没扣库存”或反之 | 如果业务可接受补偿,可改用 TCC / Saga |
| 跨分片事务 | 分库分表后,user_id=1 在 shard1,user_id=2 在 shard2;转账需同时更新两片 | 多分片同时更新,ACID 不可分裂 | ShardingSphere-Proxy 支持 2PC/XA;或业务拆分为两条幂等消息链 |
| 多存储引擎协同 | 关系型 DB + 消息队列 + 缓存同时写;必须“写 DB 成功 → MQ 确认 → 缓存刷新”三步原子 | 消息丢失会导致数据和事件流不一致 | 可采用 事务消息(RocketMQ 事务消息、Kafka 事务)代替 2PC |
| 主-主同步或 Group Replication | MySQL 组复制(Multi-Primary 模式) | 节点之间互为写库,需共识协议(Paxos/Raft 两阶段或三阶段)保证一致序 | 若只是主-从同步且读写分离,可用 半同步复制 而非 2PC |
2.2 主从复制

| 维度 | 关键要点 |
|---|---|
| 目的 | 横向扩展读能力、容灾备份、异地容灾、日志审计 |
| 角色 | 主库 (Source / Master):处理所有 DML,并记录 Binary Log (binlog) 从库 (Replica / Slave):通过复制线程把 binlog 重放,保持数据一致 |
| 核心文件/线程 | binlog (主库)I/O thread (从库):拉取并写入 relay-logSQL thread / Worker (从库):按顺序执行 relay-log 中的事件 |
| 复制模式 | - 异步 (Async):默认,主库不等待从库 ACK - 半同步 (Semi-sync):事务提交需 ≥1 从库写入 relay-log 并返回 ACK - 组复制 (Group Replication):Paxos/Raft 共识,可多主,强一致;属于更高阶 |
| 一致性等级 | 最终一致 → 半同步 < 强一致(Group Replication) |
| 配置要点 | server_id 唯一、log_bin=ON、binlog_format=ROW、gtid_mode=ON(推荐) |
| 监控指标 | Seconds_Behind_Master、Replica_IO_Running/Replica_SQL_Running、性能_schema 复制延迟视图 |
| 性能调优 | - 并行复制:replica_parallel_workers 8-16- binlog 压缩: binlog_row_image = MINIMAL- 分批写:避免超大事务 |
| 常用运维 | CHANGE MASTER TO …、START/STOP REPLICA、SHOW REPLICA STATUS\G |
| 故障切换 | MHA、Orchestrator、DolphinScheduler + VIP/Proxy;云 RDS 提供自动切主 |
| 常见坑 | - 大事务导致延迟飙升- 表无主键 → 并行复制失效- 主从时区/字符集不一致 |
| 最佳实践 | 复制链路单独网卡;定期验证备份;延迟阈值触发熔断或强制走主库; |
- 配置文件
my.cnf
-- 主库 my.cnf
server_id = 1
log_bin = mysql-bin
gtid_mode = ON
enforce_gtid_consistency = ON
-- 从库 my.cnf
server_id = 2
log_bin = mysql-bin
relay_log = relay-bin
gtid_mode = ON
enforce_gtid_consistency = ON
read_only = 1
-- 在从库执行
CHANGE MASTER TO
MASTER_HOST='master_ip',
MASTER_USER='repl',
MASTER_PASSWORD='repl_pwd',
MASTER_AUTO_POSITION=1;
START REPLICA;
2.3 写后立读
真实企业不会只靠“把主从延迟调到 0”,而是 先划分必须强一致的读路径,用“读主 / 写穿缓存”兜底,再通过半同步复制和异步索引满足大规模读,做到局部强一致 + 全局最终一致。
| 路线 | 典型做法 | 适用场景 | 成本 / 隐患 |
|---|---|---|---|
| A. 固定读主 | • 同一事务或同一连接直接 SELECT(写库已持有锁)• 提交后在同线程或显式 Hint(ShardingSphere setWriteRouteOnly、JDBC readFromMaster=true)把后续查询路由到主库 | 必须 100 % 一致:订单创建完立刻回列表、支付后立即查余额 | 读压力回流主库,需评估 QPS;Hint 需 TTL 机制防止一直读主 |
| B. 写穿缓存 | 写成功 → 同步写 Redis(或本地 Caffeine)查询先走缓存,没有命中再查从库 | 列表、详情、配置类读多写少且允许 10 s 内最终一致 | 需解决缓存雪崩 / 双写一致;数据量大时内存成本高 |
| C. 极小复制延迟 | 半同步 + 并行复制 (replica_parallel_workers),SSD、万兆网;延迟常压在 10~50 ms | 内部报表、秒杀库存等轻度实时需求 | 延迟偶发尖刺仍可能错读;部署复杂 |
| D. CQRS / 事件驱动 | 写入主库 → 发送 Kafka 事件 → ElasticSearch / ClickHouse 构建实时索引读侧完全独立 | 海量读、复杂搜索/聚合:订单中心、交易分析 | 开发量大、最终一致;需链路监控补偿 |
3. 缓存加速
3.1 应用层缓存
缓存 = 快 + 易失 + 最终一致。 设计时从 策略(读写)→ 失效 → 一致性 → 冗余 → 监控 五个维度全链路考虑,才能在提升性能的同时,避免数据脏读、击穿、雪崩与单点故障。
| 维度 | 关键要点 | 常见选项 / 做法 |
|---|---|---|
| 目标 | 加速读、削峰、隔离后端、独立横向扩容 | Redis、Memcached、本地 Caffeine |
| 典型放置 | CDN 边缘应用进程内缓存独立缓存集群 | 按数据热度、大小、更新频率分层放置 |
| 缓存策略 | - Read-Through / Cache-Aside(最常用) - Write-Through(同步写库 + 缓存) - Write-Behind / Write-Back(异步刷库) - Write-Around(直接写库,读时再填充) | 视 一致性 vs. 延迟 取舍 |
| 失效策略 | TTL(绝对过期)Idle(滑动过期)主动刷新(定时或异步消息) | 热点数据 TTL 较长 + 主动刷新;冷数据 TTL 短 |
| 驱逐策略 | LRU(默认)LFU、FIFO、Random、LIRS、ARC | Redis 6.0+ 默认 LRU |
| 一致性手段 | - 先写库再删缓存(双删) - 订阅 binlog / CDC 通知失效 - 事务消息 同步更新 | 写量大时推荐 异步失效 + 幂等读修 |
| 故障与冗余 | 主从复制 / 分片 + 哨兵多 AZ 多副本内存冗余 10-30 % 预留 | 防止 SPOF 与 OOM |
| 热点 Key 缓解 | 本地缓存 + Multi-Level Cache请求打散(随机前缀)批量合并(Collapse) | 高并发抢购/配置中心 |
| 水平扩容 | 一致性哈希代理/客户端分片Redis Cluster / Codis | 平滑扩容、避免大量重建 |
- 缓存策略
| 策略 | 读链路 | 写链路 | 一致性 & 适用场景 |
|---|---|---|---|
| Cache-Aside (Read-Through) | 先查缓存;未命中再查库并写缓存 | 先写库,再删/刷新缓存 | 简单通用;写后可能短暂脏读 |
| Write-Through | 与 Cache-Aside 相同 | 同步写 缓存→库(事务) | 数据立即一致;写延迟 ↑ |
| Write-Behind / Back | 与 Cache-Aside 相同 | 先写缓存,异步批量刷库 | 高写吞吐;崩溃可能丢数据 |
| Write-Around | 读:与 Cache-Aside 相同 | 直接写库,不写缓存 | 写缓存省内存;首次读延迟高 |
- 三级缓存
| 层级 | 延迟 | 命中率 | 容量 | 典型数据 |
|---|---|---|---|---|
| L1 本地 Caffeine | 亚微秒 | 20-40 % | 进程内 | 配置、用户会话 |
| L2 Redis/Memcached | 0.2-1 ms | 40-60 % | GB-TB | 页面片段、商品详情 |
| L3 DB / Search | 1-10 ms | 100 % | TB+ | 冷数据、全量搜索 |
3.2 网络缓存
CDN = “全球就近缓存静态资源 + 边缘网络加速”。合理设置 TTL、成本测算与故障回退,是将 CDN 真正跑稳、跑快、跑省的三大关键。
| 维度 | 关键信息 |
|---|---|
| 核心定位 | 全球多节点 缓存静态资源(图片、JS、CSS、视频、小文件下载等),让用户就近取源,降低时延、减轻源站压力 |
| 工作流程(Cache-Hit / Miss) | 1️⃣ 用户访问 CDN 域名 → 就近边缘节点 2️⃣ 命 中:直接回源文件 3️⃣ 未命中:边缘节点向源站拉取 → 按 TTL 缓存 → 返回用户 |
| 典型优势 | - 性能:把静态内容搬到离用户最近的 PoP 节点 - 节省带宽:边缘复用缓存,源站出流量大幅下降 - 安全隔离:隐藏真实源站 IP,可叠加 WAF、DDoS 防护 |
| 常见厂商 / 产品 | Cloudflare、Akamai、AWS CloudFront、阿里云 OSS+CDN、腾讯云 CDN、Fastly 等 |
| 使用最佳实践 | - 文件分层:频繁访问或大对象才进 CDN,冷文件走直链降低费用 - 合理 TTL:动态内容短 TTL 或使用版本号;静态不变资源可更长 - 回源熔断:CDN 故障时,前端自动切源或应用内降级 - 文件失效:• 调用 CDN 提供的 API 批量 Purge • URL 版本化 logo.png?v=3 |
| 成本注意 | 计费维度包括 下行流量、回源流量、请求次数;大量小文件记得合并 Sprite/Atlas,减少请求数 |
| 动态内容加速(可选) | 支持基于 Path / Query / Cookie / Header 的边缘缓存,也可结合边缘计算(Edge Function、Edge KV)进行微服务下沉,但需关注一致性与业务逻辑复杂度 |
- 负载均衡+读写分离+多服务+缓存+CDN+无状态

- 负载均衡+读写分离+多服务+缓存+CDN+有状态+数据中心

3.3 有状态 Web 架构
| 方案 | 核心做法 | 优点 | 缺点 / 隐患 | 典型场景 |
|---|---|---|---|---|
| 1. 负载均衡 Sticky Session | 通过 Cookie / IP hash / Source Port 让同一用户请求始终落在同一台 Web 服务器 | 实现最简单;代码零改动 | - 节点失效会话丢失- 扩缩容需要重新分配哈希,旧会话失效 - 负载不均,热点节点易过载 | 早期系统、会议直播等短会话 |
| 2. Web-Server Session 复制 | Tomcat、Nginx Plus、WebLogic 等把会话广播 / 点对点复制 | 无需外部存储;少量节点可故障转移 | - 节点数多时复制风暴 - 跨机房延迟高,易冲突 | 2 ~ 4 台中小集群、会话较小 |
| 3. 本地缓存 + 持久备份 | Session 写入 进程内缓存 (Ehcache/Hazelcast),异步批量刷到共享 DB | 读极快;写可批量 | 实现复杂;异步丢数据需补偿;多副本一致性难 | 高频读、低写:购物车、草稿 |
| 4. Redis Session Store | 登录成功后将 session_id → 用户数据 写入 Redis/Sentinel 或 Redis Cluster,所有 Web 节点通过 Key 读取;TTL + 滑动续期 | - 真正“状态外置”,Web 层无状态,水平扩容简单- QPS 高,毫秒级延迟;支持主从、分片,高可用 - 可设置 TTL、防雪崩、统一监控 | - 读写多一次网络 hop,依赖 Redis 可用性 - 内存成本高;大 Session 需拆分/压缩 - 主从切换瞬间可能丢写,需要 AOF/双写兜底 | 主流 Web 登录态、移动 APP Token、跨机房共享会话 |
4. 数据库扩展

| 方式 | 做法 | 典型优势 | 主要瓶颈 / 风险 |
|---|---|---|---|
| 垂直扩展(Vertical / Scale-Up) | 给同一台数据库服务器持续加 CPU、内存、SSD、网卡等 | 部署与运维最简单,短期内性能提升明显 | - 硬件上限:即使 RDS 提供 24 TB RAM 机型,也终有天花板 - 单点故障:机器宕机=数据库全线不可用 - 成本高:高端主机价格呈指数级增长 |
| 水平扩展(Horizontal / Scale-Out) | 通过分片、读写分离、多主集群,把数据和流量拆到多台服务器 | 理论上可无限扩容、具备冗余与故障切换 | 架构复杂度高,需解决分布式事务、数据同步、路由一致性等问题 |
4.1 垂直扩展
4.2 水平扩展
分片 = 数 据量和流量突破单机极限后的必经之路。选好分片键、提前规划路由与再分片策略,能让系统“既扩得动,又管得住”。
| 维度 | 核心要点 |
|---|---|
| 定义 | 把同一逻辑表的数据 按某种规则切分到多台实例 / 多张表,每块称 分片 (Shard),架构一致、数据互不重叠。 |
| 目的 | - 容量:突破单机存储/文件上限- 吞吐:并行读写,缓解热点- 隔离:故障、维护互不影响 |
| 常见分片策略 | 1) 哈希分片:user_id % N → 均衡、简单;难做范围查询。2) 范围分片:按时间、ID 段;利于区间查询,易出现冷热不均。 3) 目录分片 / 标签分片:按业务维度(国家、租户);便于合规、本地化。 |
| 分片键选择 | - 高基数、均匀分布(避免热点) - 查询 / 更新必带此键(路由精准) - 尽量不可变(变动会导致搬迁) |
| 核心组件 | - 路由层:ShardingSphere、ProxySQL、应用内 DataSourceRouter - ID 生成:雪花/Redis INCR,保证不同分片唯一 - 治理:再分片、扩容、监控 |
| 优势 | ✦ 理论无限扩容✦ 跨机房多活、容灾✦ 写并行,读并行 |
| 挑战 / 隐患 | - 跨分片查询/事务:需分布式事务或拆业务 - 热点迁移:单键高并发导致局部瓶颈 - 再分片:扩容需数据搬迁,复杂度高 - 运维监控:节点 & 路 由表同步、报警 |
| 最佳实践 | 1. 先做 读写分离,容量逼近单机极限再分片。 2. 分片前抽象 DAO 层,降低代码耦合。 3. 建立 全局唯一索引(如 ElasticSearch)处理跨分片模糊查询。 4. 监控分片热点 & 数据量,定期预分配分片或做片键二次哈希。 |
- user_id 哈希分库
- 负载均衡+读写分离+多服务+缓存+CDN+有状态+数据中心+数据分片

5. 异步化 & 松耦合
5.1 消息队列
消息队列解决“异步 + 解耦 + 削峰”,日志 / 监控 / 自动化提供“可观测 + 高效交付”,三者共同构成大规模系统的稳定运行与快速迭代基石。
| 组成 | 关键作用 | 典型技术 / 做法 |
|---|---|---|
| 消息队列(MQ) | - 解耦:生产者/消费者异步通信 - 削峰:高并发时充当缓冲 - 弹性扩容:根据队列长度动态增减 Worker | Kafka、RabbitMQ、RocketMQ、AWS SQS |
| 日志系统 | - 集中采集:Nginx/Tomcat 日志、业务日志 - 快速检索:统一索引、全文搜索 - 故障定位:异常堆栈、慢查询 | ELK/EFK(Elasticsearch + Logstash/Fluentd + Kibana)、Loki + Grafana |
| 监控与指标 | - 主机级:CPU、内存、磁盘 I/O、网络 - 组件级:DB QPS、Redis hit rate、Kafka lag - 业务级:DAU、GMV、转化率 | Prometheus + Grafana、CloudWatch、Datadog |
| 自动化 / CI & CD | - 持续集成:自动编译 + 单元测试 + 静态扫描 - 持续部署:流水线一键部署,多环境灰度 - 基础设施即代码:自动创建 / 回滚集群 | Jenkins/GitHub Actions + Argo CD、GitLab CI、Terraform/Ansible |
- 主流队列的默认行为
| 产品 | 默认 | 备注 |
|---|---|---|
| Kafka | 拉取 | 高速顺序日志,Consumer 定位 offset |
| RabbitMQ (AMQP) | 推送 | Channel 内部以信道推送,Client ACK |
| RocketMQ | 拉取,但提供 “Push Consumer” 封装 | Push 客户端内部定时拉取 |
| SQS | 拉取 | 提供长轮询防止空轮询 |
| Redis Stream | 拉取 | XREAD / XREADGROUP |
| MQTT | 推 | 典型物联网实时推送 |
- 负载均衡+读写分离+多服务+缓存+CDN+无状态+消息队列+监控
